﻿#include "Http.h"
#include"CCharSet.h"
#include<iostream>
#include <filesystem>
#include<fstream>
#include<string.h>
#include<thread>
using namespace std;
#define SendBuf 512
#define RecvBuf 1025*40


bool Http::Get(const string& url)
{
	SendRequest.setMethod();
	getHost(url, SendRequest);
	Link(SendRequest.getHost(), SendRequest.getPort());
	send(SendRequest);
	return true;
}

const string& Http::recv()
{
	//string buf;
	//cout << "接收返回数据" << endl;
	buf.clear();
	char* buff = new char[RecvBuf] {0};
	int recvSize = 0;
	do
	{
		memset(buff, 0, RecvBuf);
		recvSize = TCP::recv(buff, RecvBuf - 1);
		//buf += CCharSet::Utf8ToAnsi(buff);
		buf += buff;
		//cout<<buf;
		//cout << "recvSize:" << recvSize << endl;;
	} while (recvSize > 0);

	delete[] buff;
	//cout << buf;
	//cout << "接收结束";
	RecvRequestFun(buf);
	close();
	return buf;
}

const string Http::getText()
{
	int nSel = buf.find("\r\n\r\n");

	return buf.substr(nSel+4);
}

void Http::recv(const string& Path, const string& newName)
{
	string path=SendRequest.getResPath();
	int nSel = path.rfind("/");
	string photoName=path.substr(nSel+1);

	if (!newName.empty())//新的名字
		photoName = newName;

	path = Path + "/" + photoName;//路径和名字组合
	//filesystem::create_directory(Path);  //创建一个目录(文件夹)
	fstream file(path, ios::out | ios::binary| ios::trunc);//二进制写
	if (!file.is_open())
	{
		cout << "File creation failure"<<endl;
		return;
	}
	char* buff = new char[RecvBuf] {0};
	//排除掉文件头的"\r\n\r\n"
	int r = TCP::recv(buff, RecvBuf-1);
	RecvRequestFun(buf);
	char* p = strstr(buff, "\r\n\r\n");
	file.write(p + strlen("\r\n\r\n"), r - (p - buff) - strlen("\r\n\r\n"));

	while (1) {
		r = TCP::recv(buff, RecvBuf - 1);
		if (r > 0) {
			file.write(buff, r);
		}
		else {
			break;
		}

	}
	//保存关闭
	file.close();
	delete[] buff;
}


const vector<string> Http::strtok(const string& Text, const string& Delimiter)
{
	vector<string> ret;
	if (Text.empty() || Delimiter.empty())
		return ret;
	char* buf = new char[Text.size() + 1] {0};
	::strcpy(buf, Text.c_str());
	for (char* p = ::strtok(buf, Delimiter.c_str()); p != NULL; p = ::strtok(NULL, Delimiter.c_str()))
	{
		ret.push_back(p);
	}
	delete[] buf;
	return ret;
}

void Http::RecvRequestFun(const string& buff)
{
	//第二行开始
	int nSel1 = buff.find("\r\n") + 2;
	int nSel2= buff.find("\r\n\r\n");
	string str = buff.substr(nSel1, nSel2- nSel1);
	RecvRequest.RequestHeader.clear();
	auto temp = strtok(str,"\r\n");
	for (auto& data:temp )
	{
		auto Te= strtok(data, ":");
		RecvRequest.RequestHeader[Te[0]] = Te[1];
	}
	//cout << str;
}

long int Http::send(Request& SendRequest)
{
	//cout<<SendRequest.getGetRequest().c_str();
	int sendSize= TCP::send(SendRequest.getGetRequest().c_str(), SendRequest.getGetRequest().size()+1);
	//cout <<"发送成功:"<<sendSize<<"字节\n";
	return 0;
}
long int Http::send()
{
	return send(SendRequest);
}


void  Http::getHost(string url, Request& SendRequest)
{
	string host;
	int port=0;
	int nSel1 = url.find("//");
	if (nSel1 < 0)
	{
		cout << "url错误";
		return ;
	}
	int nSel2= url.find(":", nSel1+2);
	int nSel3 = url.find("/", nSel1+2);
	if (nSel2 < 0 && nSel3 < 0)//只有域名
	{
		host = url.substr(nSel1 + 2);
	}
	if (nSel2 > 0)
	{
		host = url.substr(nSel1 + 2, nSel2 - nSel1-2);
		string temp= url.substr(nSel2 + 1, nSel3 - nSel2);
		port = atoi(temp.c_str());
	}
	else
	{
		host = url.substr(nSel1 + 2, nSel3 - nSel1-2);
	}
	if (port == 0)
	{
		int nSel = url.find("https");
		if (nSel > 0)
			port = 443;
		else
			port = 80;
	}
	SendRequest.setHost(host, port);
	if (nSel3 > 0)
		SendRequest.setResPath(url.substr(nSel3));
	else
		SendRequest.setResPath("/");
	/*cout << host <<"\n"<<url;
	cout << port;*/
	/*return pair<string, int>(host, port);*/
}

const int Http::Link(string host, int port)
{
	int ret = 0;
	ret = TCP::socket(host, port);
	if (ret <0)//套接字失败
	{
		return ret;
	}
	do
	{
		ret=TCP::connect();
		if (ret == 0)
			break;
		std::this_thread::sleep_for(std::chrono::seconds(1));
		cout <<"1S relink" << endl;
	} while (true);
	
	setSendBuff(SendBuf);
	setRecvBuff(RecvBuf);
	return ret;
}
